
package com.rasenhund.android.grecorder.activity;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Calendar;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.sax.SAXSource;

import org.ccil.cowan.tagsoup.Parser;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.rasenhund.android.grecorder.R;
import com.rasenhund.android.grecorder.common.Const;
import com.rasenhund.android.grecorder.schema.Record;
import com.rasenhund.android.grecorder.schema.StageRecord;

/**
 * ステージ選択画面
 */
public class SelectStageActivity extends ConfirmBaseActivity {
    @SuppressWarnings("unused")
    private static final String TAG = SelectCategoryActivity.class.getSimpleName();
    private final SelectStageActivity self = this;

    Context mContext = null;

    int mStage1, mStage2; // 結果格納用変数
    String mResult = ""; // 公式ページから取得したステージ文字列

    ListView mStageList = null;
    TextView mTxtStage1 = null;
    TextView mTxtStage2 = null;
    ImageView mImgRload = null;

    /********************
     * Override Method
     ********************/
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.select_stage);

        initView();

    }

    @Override
    protected void onResume() {
        super.onResume();

        // 本日のステージの再表示
        reloadTodayStage();

    }

    /********************
     * EventListener
     ********************/
    /**
     * リスト選択時のEventListener
     */
    final OnItemClickListener lstStage_OnItemClickListener = new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

            // TODO
            // Adapterを作成していないのでpositionとStageIdがたまたま一致しているだけ、ID振りなおしなどあれば修正必須
            mAppData.setStage(position);
            jumpNext();

        }
    };

    /**
     * 再読み込み画像クリック時のEventListener
     */
    private final OnClickListener imgReload_OnClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {

            // 本日のステージの再表示
            reloadTodayStage();

        }
    };

    /********************
     * Method
     ********************/
    /**
     * Viewの初期化
     */
    private void initView() {

        mContext = getApplicationContext();

        mStageList = (ListView) findViewById(R.id.lstStage);
        mStageList.setOnItemClickListener(lstStage_OnItemClickListener);

        mTxtStage1 = (TextView) findViewById(R.id.txtTodayStage1);
        mTxtStage2 = (TextView) findViewById(R.id.txtTodayStage2);

        mImgRload = (ImageView) findViewById(R.id.imgReload);
        mImgRload.setOnClickListener(imgReload_OnClickListener);

        // 登録情報格納用変数の初期化
        mAppData.setRecord(new Record());

    }

    /**
     * 本日のステージ取得タスク実行
     */
    private void doGetStageTask() {

        // ステージ取得タスク
        AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() {

            /**
             * タスク実行前処理
             */
            @Override
            protected void onPreExecute() {
                super.onPreExecute();

                // 各種変数を初期化しておく
                mResult = "";
                mStage1 = -1;
                mStage2 = -1;

            }

            /**
             * 非同期処理実行<br>
             * 公式ページのHTMLを解析して本日のステージを取得する
             */
            @Override
            protected Boolean doInBackground(Void... params) {

                boolean bResult = true;

                InputStream in = null;
                try {

                    URL url = new URL(getString(R.string.schedule_url));
                    in = url.openStream();
                    InputSource source = new InputSource(new InputStreamReader(in, "UTF-8"));

                    XMLReader reader = new Parser();
                    DOMResult result = new DOMResult();

                    Transformer transformer =
                            TransformerFactory.newInstance().newTransformer();
                    transformer.transform(new SAXSource(reader, source), result);

                    Document document = (Document) result.getNode();

                    // ページからthタグをすべて取得する
                    NodeList thList = document.getElementsByTagName("th");
                    Node node;
                    boolean isClass, isRowSpan;
                    for (int i = 0; i < thList.getLength(); i++) {
                        node = thList.item(i);
                        NamedNodeMap attrs = node.getAttributes();

                        // Attributeを順にチェックして、以下の条件に合致するth要素からテキストを取得する
                        // 1. classが指定されていない(曜日回避用)
                        // 2. rowspan属性が指定されている

                        isClass = false;
                        isRowSpan = false;

                        for (int j = 0; j < attrs.getLength(); j++) {
                            if (attrs.item(j).getNodeName().equals("class")) {
                                isClass = true;
                            } else if (attrs.item(j).getNodeName().equals("rowspan")) {
                                isRowSpan = true;
                            }
                        }

                        if (!isClass && isRowSpan) {
                            mResult = node.getTextContent();
                        }
                    }
                } catch (Exception e) {
                    bResult = false;
                } finally {
                    if (in != null) {
                        try {
                            in.close();
                        } catch (IOException e) {
                            throw new RuntimeException();
                        }
                    }
                }

                return bResult;
            }

            /**
             * 非同期処理完了時の処理
             */
            @Override
            protected void onPostExecute(Boolean result) {

                if (!result) {

                    // エラー発生時、メッセージを表示
                    TextView txtErr = (TextView) findViewById(R.id.lblFailedMsg);
                    txtErr.setVisibility(View.VISIBLE);

                } else {

                    // データ取得成功時、検証と保存を行う

                    if (mResult.length() > 0) {
                        String[] stageList = mResult.split("／");
                        // ステージ名からコードを逆引きする
                        for (StageRecord stage : Const.getStageList(mContext)) {
                            // 1戦目のステージ
                            if (stageList.length >= 1) {
                                if (stage.getStageNm().equals(stageList[0])) {
                                    mStage1 = stage.getStageCd();
                                }
                            }
                            // 2戦目のステージ（あれば）
                            if (stageList.length >= 2) {
                                if (stage.getStageNm().equals(stageList[1])) {
                                    mStage2 = stage.getStageCd();
                                }
                            }
                        }

                        if (mStage1 != -1 || mStage2 != -1) {

                            // 次回取得を省略するため日付をPreferenceに書き込む
                            Calendar cal = Calendar.getInstance();
                            String sDate = "";
                            sDate = sDate + String.valueOf(cal.get(Calendar.YEAR));
                            sDate = sDate + String.valueOf(cal.get(Calendar.MONDAY));
                            sDate = sDate + String.valueOf(cal.get(Calendar.DATE));

                            SharedPreferences pref = getSharedPreferences(Const.PREFERENCE_NAME,
                                    MODE_PRIVATE);
                            Editor editor = pref.edit();
                            editor.putString(Const.KEY.KEY_LAST_DATE, sDate);
                            editor.putInt(Const.KEY.KEY_STAGE1, mStage1);
                            editor.putInt(Const.KEY.KEY_STAGE2, mStage2);
                            editor.commit();

                        }

                    }

                }

            }

        };
        task.execute();

    }

    /**
     * カテゴリ選択画面へ遷移
     */
    private void jumpNext() {

        Intent intent = new Intent(self, SelectCategoryActivity.class);
        startActivity(intent);

    }

    /**
     * 取得したステージ情報を画面に反映
     */
    private void setStageInfo() {

        if (mStage1 != -1) {
            mTxtStage1.setText(Const.getStageNm(self, mStage1));
            mTxtStage1.setOnTouchListener(new OnTouchListener() {
                @Override
                public boolean onTouch(View arg0, MotionEvent arg1) {
                    mAppData.setStage(mStage1);
                    jumpNext();
                    return false;
                }
            });
            mTxtStage1.setVisibility(View.VISIBLE);
            mImgRload.setVisibility(View.GONE);
        }

        if (mStage2 != -1) {
            mTxtStage2.setText(Const.getStageNm(self, mStage2));
            mTxtStage2.setOnTouchListener(new OnTouchListener() {
                @Override
                public boolean onTouch(View arg0, MotionEvent arg1) {
                    mAppData.setStage(mStage2);
                    jumpNext();
                    return false;
                }
            });
            mTxtStage2.setVisibility(View.VISIBLE);
            mImgRload.setVisibility(View.GONE);
        }

    }

    /**
     * ステージが取得済みかどうかの判定
     * 
     * @return
     */
    private boolean isAcquired() {

        SharedPreferences pref = getSharedPreferences(Const.PREFERENCE_NAME, MODE_PRIVATE);
        String lastDate = pref.getString(Const.KEY.KEY_LAST_DATE, "");

        Calendar cal = Calendar.getInstance();
        String sDate = "";
        sDate = sDate + String.valueOf(cal.get(Calendar.YEAR));
        sDate = sDate + String.valueOf(cal.get(Calendar.MONDAY));
        sDate = sDate + String.valueOf(cal.get(Calendar.DATE));

        if (lastDate.equals(sDate)) {
            // 取得日が本日なら保存していた値を取得する
            mStage1 = pref.getInt(Const.KEY.KEY_STAGE1, -1);
            mStage2 = pref.getInt(Const.KEY.KEY_STAGE2, -1);
            return true;
        }

        return false;
    }

    /**
     * 本日のステージの再読み込み
     */
    private void reloadTodayStage() {

        if (isAcquired()) {
            // 取得済みのステージ情報を画面にセット
            setStageInfo();
        } else {
            // ステージ取得タスクを実行
            doGetStageTask();
        }

    }

}
